# -*- coding:utf-8 -*-
import datetime
import os

from datetime import timedelta
from pathlib import Path

from flask import Flask, request
from flask_sqlalchemy import get_debug_queries

import ext
# from ext import db, bootstrap, cache, cors, jwt, interface,csrf

from ext import db, bootstrap, cache, cors, api, jwt
# 导入蓝图
# from . import user
from .interface.views import interface_bp
from .app.views import app_bp
from .data.views import data_bp
from .user.views import user_bp1
# from .data.mysqltest import sqldata_bp

from datamp.user.models import *
from datamp.data.models import *

# from .web import web
import settings

from datamp.user.models import RevokeTokenModel

# 加载日志
import logging
import logging.handlers
from logging import FileHandler
from logging.handlers import RotatingFileHandler
from logging.handlers import TimedRotatingFileHandler

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration
import socket
import traceback
from flask import current_app



# 递归创建日志存放目录
basedir = Path(__file__).parent.parent  # 项目根目录
logdir = basedir.joinpath(r'rethink/logs')
if not logdir.is_dir():
    os.makedirs(logdir)

# 初始化Sentry, 必须在工厂函数之前
sentry_sdk.init(
    dsn="https://0ec60cde076e4618948dc510bc6b7bec@o1033887.ingest.sentry.io/6000536",
    integrations=[FlaskIntegration()],
    # Set traces_sample_rate to 1.0 to capture 100%
    # of transactions for performance monitoring.
    # We recommend adjusting this value in production.
    traces_sample_rate=1.0
)


# 自定义一个LogFilter
class ContextFilter(logging.Filter):
    """Enhances log messages with contextual information"""
    def filter(self, record):
        record.hostname = "e2lab-hbh_test"
        return True


config = {
    'CACHE_TYPE': 'redis',
    'CACHE_REDIS_HOST': '127.0.0.1',
    'CACHE_REDIS_PORT': 6379,

    'JWT_SECRET_KEY': 'dd',
    'JWT_BLACKLIST_ENABLED': True,
    'JWT_BLACKLIST_TOKEN_CHECKS': ['access', 'refresh'],
    'JWT_ACCESS_TOKEN_EXPIRES': timedelta(hours=1),  # 设置access_token的有效时间
    'JWT_REFRESH_TOKEN_EXPIRES': timedelta(days=1),  # 设置refresh_token的有效时间

    'RECAPTCHA_PUBLIC_KEY': '6LeYIbsSAAAAACRPIllxA7wvXjIE411PfdB2gt2J',
    'RECAPTCHA_PRIVATE_KEY': '6LeYIbsSAAAAAJezaIq3Ft_hSTo0YtyeFG-JgRtu',
    'RECAPTCHA_PARAMETERS': {'hl': 'zh', 'render': 'explicit'},
    'RECAPTCHA_DATA_ATTRS': {'theme': 'dark'},
}


def register_logger(app):
    #--机器名--
    # HOST_NAME = socket.gethostname()
    #--机器ip--
    # IP = socket.gethostbyname(HOST_NAME)
    #--记录格式['+HOST_NAME+']['+IP+']
    LOGGING_MSG_FORMAT = '(%(hostname)s)[%(asctime)s][%(filename)s:%(lineno)d][%(levelname)s][%(thread)d] - %(message)s'
    formatter = logging.Formatter(LOGGING_MSG_FORMAT)
    # 按照时间划分
    file_handler = TimedRotatingFileHandler(logdir.joinpath('runtime.log'), when="D", interval=1, backupCount=3, encoding="UTF-8",delay=False,utc=True)
    file_handler.setFormatter(formatter)
    file_handler.setLevel(logging.INFO)
    file_handler.addFilter(ContextFilter())
    app.logger.addHandler(file_handler)



def error_log(e):
    current_app.logger.error(traceback.format_exc())
    return '404'


def create_app():
    app = Flask(__name__)
    app.config.from_object(settings.DevelopmentConfig)

    # app.debug = True
    db.init_app(app)  # 将db对象与app进行关联
    # 初始化bootstrap
    bootstrap.init_app(app=app)
    # 初始化缓存文件
    cache.init_app(app=app, config=config)
    # 跨域
    cors.init_app(app=app, supports_credentials=True)
    # interface
    ext.api.init_app(app=app)
    # jwt鉴权
    jwt.init_app(app=app)

    # flask-wtf csrf验证
    # csrf.init_app(app=app)

    # 日志
    # register_logger(app=app)
    # app.logger.error(error_log(Exception))
    # app.errorhandler(Exception)(error_log)
    # app.logger.error(traceback.format_exc())
    # 如果没有未处理的异常抛出，会在每个请求结束后运行
    # 必须接受一个响应类对象作为参数，并返回同一个或更新后的响应对象

    # 注册蓝图
    app.register_blueprint(user_bp1)
    app.register_blueprint(interface_bp)
    app.register_blueprint(app_bp)
    app.register_blueprint(data_bp)
    # app.register_blueprint(sqldata_bp)

    return app


@jwt.token_in_blocklist_loader
def check_if_token_in_blacklist(*args):
    jti = args[1]['jti']
    isrevoked = RevokeTokenModel.is_jti_blacklisted(jti)
    return isrevoked
